package com.tang.common.aspect;

import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSON;
import com.tang.common.annotation.ApiLog;
import com.tang.common.event.ApiLogEvent;
import com.tang.common.utils.CommonUtils;
import com.tang.module.system.entity.LogApi;
import com.tang.module.system.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 日志切面处理类
 * @author tang
 * @date 2022/1/18 18:01
 */
@Aspect
@Component
public class ApiLogAop {

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Value("${spring.profiles.active}")
    private String profiles;


    @Value("${spring.application.name}")
    private String name;

    @Around("@annotation(apiLog)")
    private Object logAround(ProceedingJoinPoint joinPoint, ApiLog apiLog) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获得当前请求
        HttpServletRequest request = attributes.getRequest();
        LogApi logApi = new LogApi();
        //获得当前用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() != null){
            User user = (User)authentication.getPrincipal();
            logApi.setCreateBy(user.getAccount());
        }
        logApi.setCreateTime(new Date());
        logApi.setMethod(request.getMethod());
        logApi.setRequestUri(request.getRequestURI());
        logApi.setRemoteIp(CommonUtils.getIpAddr(request));
        logApi.setType(String.valueOf(apiLog.type()));
        logApi.setTitle(apiLog.title());
        logApi.setParams(StringUtils.isEmpty(request.getParameterMap()) || request.getParameterMap().size() == 0 ? "无参数" : JSON.toJSONString(request.getParameterMap()));
        logApi.setEnv(profiles);
        logApi.setServerHost(name);
        logApi.setMethodClass(joinPoint.getSignature().getDeclaringTypeName());
        logApi.setMethodName(joinPoint.getSignature().getName());
        //获取用户代理
        UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent"));
        logApi.setBrowser(ua.getBrowser().toString());
        logApi.setSystem(ua.getPlatform().toString());
        logApi.setMobileTerminal(ua.isMobile());
        long l = System.currentTimeMillis();
        //放行
        Object proceed;
        try {
            proceed = joinPoint.proceed();
            applicationEventPublisher.publishEvent(new ApiLogEvent(logApi));
            //记录请求耗时
            logApi.setTime(String.valueOf(System.currentTimeMillis() - l));
            logApi.setSuccess(true);
        } catch (Throwable e) {
            //记录请求耗时
            logApi.setTime(String.valueOf(System.currentTimeMillis() - l));
            logApi.setSuccess(false);
            logApi.setExceptionMsg(e.getMessage());
            applicationEventPublisher.publishEvent(new ApiLogEvent(logApi));
            throw e;
        }
        return proceed;
    }
}
